#include "threadpool.h"

// 启动线程

Thread::Thread(ThreadFunc func)
{
    this->threadId_ = generateId_++;
    this->func_ = func;
}
Thread::~Thread()
{
}

void Thread::start()
{
    // 执行一个线程函数
    std::thread t(func_, threadId_);
    t.detach(); // 设置分离线程
}

int Thread::getId() const
{
    return threadId_;
}
int Thread::generateId_ = 0;

ThreadPool::ThreadPool() : initThreadSize_(4),
                           taskSize_(0),
                           taskSizeThreshHold_(TASK_MAX_THRESHHOLD),
                           poolmode_(PoolMode::MODE_FIXED), // 固定模式
                           isPoolRunning_(false),
                           idleThreadSize_(0),
                           threadMaxSize(THREAD_MAX_THRESHHOLD),
                           curThreadSumSize_(0)
{
}
ThreadPool::~ThreadPool()
{
    isPoolRunning_ = false;
    notEmpty_.notify_all();
    std::unique_lock<std::mutex> lock(taskQueMtx_);
    exitCond_.wait(lock, [&]() -> bool
                   { return threads_.size() == 0; });
}

void ThreadPool::setMode(PoolMode mode)
{
    if (checkRunningState())
        return;
    poolmode_ = mode;
}

void ThreadPool::setTaskMaxSize(int size)
{
    if (checkRunningState())
        return;
    this->taskSizeThreshHold_ = size;
}

// 设置chched模式下线程的最大值
void ThreadPool::setThreadSizeMAx(int size)
{
    if (checkRunningState())
        return;
    if (poolmode_ == PoolMode::MODE_CACHED)
    {
        this->threadMaxSize = size;
    }
}

void ThreadPool::start(int initThreadSize ) // 开启线程池
{
    // 设置线程池的运行状态
    isPoolRunning_ = true;

    // 记录线程个数
    this->initThreadSize_ = initThreadSize;
    this->curThreadSumSize_ = initThreadSize;
    for (int i = 0; i < initThreadSize_; i++)
    {
        auto ptr = std::make_unique<Thread>(std::bind(&ThreadPool::threadFunc, this, std::placeholders::_1));
        // threads_.emplace_back(std::move(ptr));
        int threadId = ptr->getId();
        threads_.emplace(threadId, std::move(ptr));
    }
    for (int i = 0; i < initThreadSize_; i++)
    {
        threads_[i]->start();
        idleThreadSize_++; // 记录初始空闲线程数量
    }
}

// 定义线程函数
void ThreadPool::threadFunc(int threadid)
{
    // std::cout << "begin threadFunc tid:" << std::this_thread::get_id() << std:: endl;
    // std::cout << "end threadFunc tid:" << std::this_thread::get_id() << std::endl;

    auto lastTime = std::chrono::high_resolution_clock().now();
    while (isPoolRunning_)
    {
        std::function<void()> task;
        {
            // 获取锁
            std::unique_lock<std::mutex> lock(taskQueMtx_);
          
            // cached模式下创建多的线程如果空闲60s得回收
            // 判断是不是超时返回，还是有任务阻塞
            while (tasks_.size() == 0)
            {
                if (poolmode_ == PoolMode::MODE_CACHED)
                {
                    if (std::cv_status::timeout ==
                        notFull_.wait_for(lock, std::chrono::seconds(1)))
                    {
                        auto now = std::chrono::high_resolution_clock().now();
                        auto dur = std::chrono::duration_cast<std::chrono::seconds>(now - lastTime);
                        if (dur.count() >= 60 &&
                            curThreadSumSize_ > initThreadSize_)
                        {
                            // 开始回收当前线程
                            threads_.erase(threadid);
                            curThreadSumSize_--;
                            idleThreadSize_--;
                            // std::cout << "threadid" << std::this_thread::get_id() << "exit" << std::endl;
                            return;
                        }
                    }
                }
                else
                {
                    notEmpty_.wait(lock);
                }
                // 线程池要结束
                if (!isPoolRunning_)
                {
                    threads_.erase(threadid);
                    curThreadSumSize_--;
                    idleThreadSize_--;
                    // std::cout << "threadid" << std::this_thread::get_id() << "exit" << std::endl;
                    exitCond_.notify_all(); // 因为主线程在等待，如果这里不通知，会产生死锁问题
                    return;
                }
            }
            // std::cout << "tid:" << std::this_thread::get_id() << "获取任务成功.." << std::endl;
            idleThreadSize_--;

            task = tasks_.front();
            tasks_.pop();
            taskSize_--;
            // 如果依然有任务，继续通知
            if (tasks_.size() > 0)
            {
                notEmpty_.notify_all();
            }
            // 取出一个任务，进行通知。可以继续提交任务
            notFull_.notify_all();
        }
        // 执行任务
        if (task)
        {
            task();
        }
        lastTime = std::chrono::high_resolution_clock().now();
        idleThreadSize_++;
    }

    threads_.erase(threadid);
    curThreadSumSize_--;
    idleThreadSize_--;
    exitCond_.notify_all();
    // std::cout << "threadid" << std::this_thread::get_id() << "exit" << std::endl;
}


 //检查pool的运行状态
 bool ThreadPool::checkRunningState()const
 {
     return isPoolRunning_;
 }